package gui;

import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import problem.GraphColoringEPM;

public class MetalearnerController implements Initializable {

	GraphColoringEPM gcpEPM;
	Thread ePMThread;
	List<File> fileList;

	@FXML TabPane root;

	@FXML Button loadgcp;
	@FXML Button genModel;
	@FXML Button bLoadXARFF;
	@FXML Button bGenRandomGraph;
	
	@FXML TextField txXARFFPath;

	@FXML ListView<String> lvInstances;
	@FXML Label lNumberOfInstances;
	@FXML Label lFeaturesSelected;

	@FXML CheckBox cbAllFeatures;
	
	@FXML CheckBox cbNodes;
	@FXML CheckBox cbEdges;
	@FXML CheckBox cbNodesEdges;
	@FXML CheckBox cbEdgesNodes;
	@FXML CheckBox cbDensity;

	@FXML CheckBox cbMinDegree;
	@FXML CheckBox cbMaxDegree;
	@FXML CheckBox cbMeanDegree;
	@FXML CheckBox cbStdDegree;
	@FXML CheckBox cbVCDegree;
	@FXML CheckBox cbMedianDegree;
	@FXML CheckBox cbQ1Degree;
	@FXML CheckBox cbQ3Degree;

	@FXML CheckBox cbMinBetweenness;
	@FXML CheckBox cbMaxBetweenness;
	@FXML CheckBox cbMeanBetweenness;
	@FXML CheckBox cbStdBetweenness;
	@FXML CheckBox cbVCBetweenness;
	@FXML CheckBox cbMedianBetweenness;
	@FXML CheckBox cbQ1Betweenness;
	@FXML CheckBox cbQ3Betweenness;

	@FXML CheckBox cbMinCloseness;
	@FXML CheckBox cbMaxCloseness;
	@FXML CheckBox cbMeanCloseness;
	@FXML CheckBox cbStdCloseness;
	@FXML CheckBox cbVCCloseness;
	@FXML CheckBox cbMedianCloseness;
	@FXML CheckBox cbQ1Closeness;
	@FXML CheckBox cbQ3Closeness;

	@FXML CheckBox cbMinEigenvector;
	@FXML CheckBox cbMaxEigenvector;
	@FXML CheckBox cbMeanEigenvector;
	@FXML CheckBox cbStdEigenvector;
	@FXML CheckBox cbVCEigenvector;
	@FXML CheckBox cbMedianEigenvector;	
	@FXML CheckBox cbQ1Eigenvector;	
	@FXML CheckBox cbQ3Eigenvector;	

	@FXML CheckBox cbMinEccentricity;
	@FXML CheckBox cbMaxEccentricity;
	@FXML CheckBox cbMeanEccentricity;
	@FXML CheckBox cbStdEccentricity;
	@FXML CheckBox cbVCEccentricity;
	@FXML CheckBox cbMedianEccentricity;
	@FXML CheckBox cbQ1Eccentricity;
	@FXML CheckBox cbQ3Eccentricity;

	@FXML CheckBox cbMinClustering;
	@FXML CheckBox cbMaxClustering;
	@FXML CheckBox cbMeanClustering;
	@FXML CheckBox cbStdClustering;
	@FXML CheckBox cbVCClustering;
	@FXML CheckBox cbMedianClustering;
	@FXML CheckBox cbQ1Clustering;
	@FXML CheckBox cbQ3Clustering;

	@FXML CheckBox cbMinWClustering;
	@FXML CheckBox cbMaxWClustering;
	@FXML CheckBox cbMeanWClustering;
	@FXML CheckBox cbStdWClustering;
	@FXML CheckBox cbVCWClustering;
	@FXML CheckBox cbMedianWClustering;
	@FXML CheckBox cbQ1WClustering;
	@FXML CheckBox cbQ3WClustering;
	
	//Graph Spectra - Adjacency Matrix
	@FXML CheckBox cbIndex;
	@FXML CheckBox cb2ndLargestAdjEgv;
	@FXML CheckBox cb2ndSmallestAdjEgv;
	@FXML CheckBox cbSmallestAdjEgv;
	@FXML CheckBox cbMeanSpectrum;
	@FXML CheckBox cbStdSpectrum;
	@FXML CheckBox cbVCSpectrum;
	@FXML CheckBox cbEnergy;
	@FXML CheckBox cbGapLargestAnd2ndLargestAdjEgv;
	
	//Graph Spectra - Laplacian Matrix
	@FXML CheckBox cbLaplacianIndex;
	@FXML CheckBox cb2ndLargestLapEgv;
	@FXML CheckBox cbSmallestNZLapEgv;
	@FXML CheckBox cb2ndSmallestNZLapEgv;
	@FXML CheckBox cbAlgConnectivity;
	@FXML CheckBox cbSmallestLapEgv;
	@FXML CheckBox cbGapLargestAndSmallestNZLapEgv;
	
	//Graph Spectra - Distance Matrix
	@FXML CheckBox cbWienerIndex;
	@FXML CheckBox cbPathLength;
	@FXML CheckBox cbGirth;
	@FXML CheckBox cbConnectedComponents;
	@FXML CheckBox cbRank;
	@FXML CheckBox cbCoRank;
	
	@FXML CheckBox cbLargestMaximalClique;
	
	@FXML CheckBox cbDegeneracy;

	@FXML ProgressIndicator pbGeneratorProgress;
	
	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
		gcpEPM = new GraphColoringEPM();
	}

	/*
	 *Pops-up a dialog asking the user to provide the list of Graph Coloring instances
	 * that will be used for feature calculation
	 */
	@FXML protected void loadGraphColoringInstances(MouseEvent event) {
		FileChooser fileChooser = new FileChooser();
		fileChooser.setTitle("Open Resource File");
		fileList = fileChooser.showOpenMultipleDialog(loadgcp.getScene().getWindow());
		ObservableList<String> obsFileList = FXCollections.observableArrayList();
		lvInstances.getItems().clear();
		for (int i=0; i<fileList.size();i++)
			if (fileList.get(i)!= null) {
				obsFileList.add(fileList.get(i).getName());
				lvInstances.setItems(obsFileList);
				lNumberOfInstances.setText("# of Instances: "+(i+1));
			}
	}

	/*
	 * Pops-up a dialog asking the user to provide a directory where the ARFF files will be
	 * created.
	 * This function also creates a new thread of GraphColoringEPM that will be used for the
	 * feature calculation/extraction.
	 * If the checkbox for the feature is selected/marked, the feature will be calculated,
	 * otherwise it won't.
	 */
	@FXML protected void generateModel(MouseEvent event) {
		DirectoryChooser directoryChooser = new DirectoryChooser();
		ePMThread = new Thread(gcpEPM);
		
		//Basic features
		gcpEPM.setNumberOfNodes(cbNodes.isSelected());
		gcpEPM.setNumberOfEdges(cbEdges.isSelected());
		gcpEPM.setNodesEdges(cbNodesEdges.isSelected());
		gcpEPM.setEdgesNodes(cbEdgesNodes.isSelected());
		gcpEPM.setDensity(cbDensity.isSelected());
		
		//Degree features
		gcpEPM.setMinDegree(cbMinDegree.isSelected());
		gcpEPM.setMaxDegree(cbMaxDegree.isSelected());
		gcpEPM.setMeanDegree(cbMeanDegree.isSelected());
		gcpEPM.setStdDegree(cbStdDegree.isSelected());
		gcpEPM.setVCDegree(cbVCDegree.isSelected());
		gcpEPM.setMedianDegree(cbMedianDegree.isSelected());
		gcpEPM.setQ1Degree(cbQ1Degree.isSelected());
		gcpEPM.setQ3Degree(cbQ3Degree.isSelected());
		
		//Betweenness Centrality features
		gcpEPM.setMinBtwnsCentrality(cbMinBetweenness.isSelected());
		gcpEPM.setMaxBtwnsCentrality(cbMaxBetweenness.isSelected());
		gcpEPM.setMeanBtwnsCentrality(cbMeanBetweenness.isSelected());
		gcpEPM.setStdBtwnsCentrality(cbStdBetweenness.isSelected());
		gcpEPM.setVCBtwnsCentrality(cbVCBetweenness.isSelected());
		gcpEPM.setMedianBtwns(cbMedianBetweenness.isSelected());
		gcpEPM.setQ1Btwns(cbQ1Betweenness.isSelected());
		gcpEPM.setQ3Btwns(cbQ3Betweenness.isSelected());
		
		//Closeness features
		gcpEPM.setMinCloseness(cbMinCloseness.isSelected());
		gcpEPM.setMaxCloseness(cbMaxCloseness.isSelected());
		gcpEPM.setMeanCloseness(cbMeanCloseness.isSelected());
		gcpEPM.setStdCloseness(cbStdCloseness.isSelected());
		gcpEPM.setVCCloseness(cbVCCloseness.isSelected());
		gcpEPM.setMedianCloseness(cbMedianCloseness.isSelected());
		gcpEPM.setQ1Closeness(cbQ1Closeness.isSelected());
		gcpEPM.setQ3Closeness(cbQ3Closeness.isSelected());
		
		//Eigenvector Centrality features
		gcpEPM.setMinEgvCentrality(cbMinEigenvector.isSelected());
		gcpEPM.setMaxEgvCentrality(cbMaxEigenvector.isSelected());
		gcpEPM.setMeanEgvCentrality(cbMeanEigenvector.isSelected());
		gcpEPM.setStdEgvCentrality(cbStdEigenvector.isSelected());
		gcpEPM.setVCEgvCentrality(cbVCEigenvector.isSelected());
		gcpEPM.setMedianEgvCentrality(cbMedianEigenvector.isSelected());
		gcpEPM.setQ1EgvCentrality(cbQ1Eigenvector.isSelected());
		gcpEPM.setQ3EgvCentrality(cbQ3Eigenvector.isSelected());
		
		//Eccentricity features
		gcpEPM.setMinEccentricity(cbMinEccentricity.isSelected());
		gcpEPM.setMaxEccentricity(cbMaxEccentricity.isSelected());
		gcpEPM.setMeanEccentricity(cbMeanEccentricity.isSelected());
		gcpEPM.setStdEccentricity(cbStdEccentricity.isSelected());
		gcpEPM.setMedianEccentricity(cbMedianEccentricity.isSelected());
		gcpEPM.setQ1Eccentricity(cbQ1Eccentricity.isSelected());
		gcpEPM.setQ3Eccentricity(cbQ3Eccentricity.isSelected());
		
		//Local Clustering features
		gcpEPM.setMinLocalClustering(cbMinClustering.isSelected());
		gcpEPM.setMaxLocalClustering(cbMaxClustering.isSelected());
		gcpEPM.setMeanLocalClustering(cbMeanClustering.isSelected());
		gcpEPM.setStdLocalClustering(cbStdClustering.isSelected());
		gcpEPM.setVCLocalClustering(cbVCClustering.isSelected());
		gcpEPM.setMedianClustering(cbMedianClustering.isSelected());
		gcpEPM.setQ1Clustering(cbQ1Clustering.isSelected());
		gcpEPM.setQ3Clustering(cbQ3Clustering.isSelected());
		
		//Weighted local clustering features
		gcpEPM.setMinLocalWClustering(cbMinWClustering.isSelected());
		gcpEPM.setMaxLocalWClustering(cbMaxWClustering.isSelected());
		gcpEPM.setMeanLocalWClustering(cbMeanWClustering.isSelected());
		gcpEPM.setStdLocalWClustering(cbStdWClustering.isSelected());
		gcpEPM.setVCLocalWClustering(cbVCWClustering.isSelected());
		gcpEPM.setMedianWClustering(cbMedianWClustering.isSelected());
		gcpEPM.setQ1WClustering(cbQ1WClustering.isSelected());
		gcpEPM.setQ3WClustering(cbQ3WClustering.isSelected());
	
		//Adjacency Matrix features (Spectrum)
		gcpEPM.setIndex(cbIndex.isSelected());
		gcpEPM.set2ndLargestAdjEgv(cb2ndLargestAdjEgv.isSelected());
		gcpEPM.set2ndSmallestAdjEgv(cb2ndSmallestAdjEgv.isSelected());
		gcpEPM.setSmallestAdjEgv(cbSmallestAdjEgv.isSelected());
		gcpEPM.setMeanSpectrum(cbMeanSpectrum.isSelected());
		gcpEPM.setStdSpectrum(cbStdSpectrum.isSelected());
		gcpEPM.setVCSpectrum(cbVCSpectrum.isSelected());
		gcpEPM.setEnergy(cbEnergy.isSelected());
		gcpEPM.setgapLargestAnd2ndLargestAdj(cbGapLargestAnd2ndLargestAdjEgv.isSelected());
		
		//Laplacian Matrix features
		gcpEPM.setLaplacianIndex(cbLaplacianIndex.isSelected());
		gcpEPM.setSecondLargestLapEgv(cb2ndLargestLapEgv.isSelected());
		gcpEPM.setSmallestNZLapEgv(cbSmallestNZLapEgv.isSelected());
		gcpEPM.setSecondSmallestNZLapEgv(cb2ndSmallestNZLapEgv.isSelected());
		gcpEPM.setAlgConnectivity(cbAlgConnectivity.isSelected());
		gcpEPM.setSmallestLapEgv(cbSmallestLapEgv.isSelected());
		gcpEPM.setgapLargestAndSmallestNZLap(cbGapLargestAndSmallestNZLapEgv.isSelected());
		
		//Other features
		gcpEPM.setWienerIndex(cbWienerIndex.isSelected());
		gcpEPM.setAvgPathLength(cbPathLength.isSelected());
		gcpEPM.setGirth(cbGirth.isSelected());
		gcpEPM.setConnectedComponents(cbConnectedComponents.isSelected());
		gcpEPM.setRank(cbRank.isSelected());
		gcpEPM.setCoRank(cbCoRank.isSelected());
		gcpEPM.setSizeLargestMaximalClique(cbLargestMaximalClique.isSelected());
		gcpEPM.setDegeneracy(cbDegeneracy.isSelected());
		
		directoryChooser.setTitle("Save Generated Model to ARFF");
		File directory = directoryChooser.showDialog(genModel.getScene().getWindow());
		if (directory != null) {
			gcpEPM.setInstancesFiles(fileList);
			gcpEPM.setTargetDirectory(directory);
			pbGeneratorProgress.progressProperty().bind(gcpEPM.progressProperty());
			ePMThread.start();
		}
	}

	/*
	 * Allows the user to click once and (de)select all features
	 */
	@FXML protected void checkAllFeatures(MouseEvent event) {
		cbNodes.setSelected(cbAllFeatures.isSelected());
		cbEdges.setSelected(cbAllFeatures.isSelected());
		cbNodesEdges.setSelected(cbAllFeatures.isSelected());
		cbEdgesNodes.setSelected(cbAllFeatures.isSelected());
		cbDensity.setSelected(cbAllFeatures.isSelected());

		cbMinDegree.setSelected(cbAllFeatures.isSelected());
		cbMaxDegree.setSelected(cbAllFeatures.isSelected());
		cbMeanDegree.setSelected(cbAllFeatures.isSelected());
		cbStdDegree.setSelected(cbAllFeatures.isSelected());
		cbVCDegree.setSelected(cbAllFeatures.isSelected());
		cbMedianDegree.setSelected(cbAllFeatures.isSelected());
		cbQ1Degree.setSelected(cbAllFeatures.isSelected());
		cbQ3Degree.setSelected(cbAllFeatures.isSelected());

		cbMinBetweenness.setSelected(cbAllFeatures.isSelected());
		cbMaxBetweenness.setSelected(cbAllFeatures.isSelected());
		cbMeanBetweenness.setSelected(cbAllFeatures.isSelected());
		cbStdBetweenness.setSelected(cbAllFeatures.isSelected());
		cbVCBetweenness.setSelected(cbAllFeatures.isSelected());
		cbMedianBetweenness.setSelected(cbAllFeatures.isSelected());
		cbQ1Betweenness.setSelected(cbAllFeatures.isSelected());
		cbQ3Betweenness.setSelected(cbAllFeatures.isSelected());

		cbMinCloseness.setSelected(cbAllFeatures.isSelected());
		cbMaxCloseness.setSelected(cbAllFeatures.isSelected());
		cbMeanCloseness.setSelected(cbAllFeatures.isSelected());
		cbStdCloseness.setSelected(cbAllFeatures.isSelected());
		cbVCCloseness.setSelected(cbAllFeatures.isSelected());
		cbMedianCloseness.setSelected(cbAllFeatures.isSelected());
		cbQ1Closeness.setSelected(cbAllFeatures.isSelected());
		cbQ3Closeness.setSelected(cbAllFeatures.isSelected());

		cbMinEigenvector.setSelected(cbAllFeatures.isSelected());
		cbMaxEigenvector.setSelected(cbAllFeatures.isSelected());
		cbMeanEigenvector.setSelected(cbAllFeatures.isSelected());
		cbStdEigenvector.setSelected(cbAllFeatures.isSelected());
		cbVCEigenvector.setSelected(cbAllFeatures.isSelected());
		cbMedianEigenvector.setSelected(cbAllFeatures.isSelected());	
		cbQ1Eigenvector.setSelected(cbAllFeatures.isSelected());	
		cbQ3Eigenvector.setSelected(cbAllFeatures.isSelected());	

		cbMinEccentricity.setSelected(cbAllFeatures.isSelected());
		cbMaxEccentricity.setSelected(cbAllFeatures.isSelected());
		cbMeanEccentricity.setSelected(cbAllFeatures.isSelected());
		cbStdEccentricity.setSelected(cbAllFeatures.isSelected());
		cbVCEccentricity.setSelected(cbAllFeatures.isSelected());
		cbMedianEccentricity.setSelected(cbAllFeatures.isSelected());
		cbQ1Eccentricity.setSelected(cbAllFeatures.isSelected());
		cbQ3Eccentricity.setSelected(cbAllFeatures.isSelected());

		cbMinClustering.setSelected(cbAllFeatures.isSelected());
		cbMaxClustering.setSelected(cbAllFeatures.isSelected());
		cbMeanClustering.setSelected(cbAllFeatures.isSelected());
		cbStdClustering.setSelected(cbAllFeatures.isSelected());
		cbVCClustering.setSelected(cbAllFeatures.isSelected());
		cbMedianClustering.setSelected(cbAllFeatures.isSelected());
		cbQ1Clustering.setSelected(cbAllFeatures.isSelected());
		cbQ3Clustering.setSelected(cbAllFeatures.isSelected());
		
		cbMinWClustering.setSelected(cbAllFeatures.isSelected());
		cbMaxWClustering.setSelected(cbAllFeatures.isSelected());
		cbMeanWClustering.setSelected(cbAllFeatures.isSelected());
		cbStdWClustering.setSelected(cbAllFeatures.isSelected());
		cbVCWClustering.setSelected(cbAllFeatures.isSelected());
		cbMedianWClustering.setSelected(cbAllFeatures.isSelected());
		cbQ1WClustering.setSelected(cbAllFeatures.isSelected());
		cbQ3WClustering.setSelected(cbAllFeatures.isSelected());
		
		//Graph Spectra - Adjacency Matrix
		cbIndex.setSelected(cbAllFeatures.isSelected());
		cb2ndLargestAdjEgv.setSelected(cbAllFeatures.isSelected());
		cb2ndSmallestAdjEgv.setSelected(cbAllFeatures.isSelected());
		cbSmallestAdjEgv.setSelected(cbAllFeatures.isSelected());
		cbMeanSpectrum.setSelected(cbAllFeatures.isSelected());
		cbStdSpectrum.setSelected(cbAllFeatures.isSelected());
		cbVCSpectrum.setSelected(cbAllFeatures.isSelected());
		cbEnergy.setSelected(cbAllFeatures.isSelected());
		cbGapLargestAnd2ndLargestAdjEgv.setSelected(cbAllFeatures.isSelected());
		
		//Graph Spectra - Laplacian Matrix
		cbLaplacianIndex.setSelected(cbAllFeatures.isSelected());
		cb2ndLargestLapEgv.setSelected(cbAllFeatures.isSelected());
		cbSmallestNZLapEgv.setSelected(cbAllFeatures.isSelected());
		cb2ndSmallestNZLapEgv.setSelected(cbAllFeatures.isSelected());
		cbAlgConnectivity.setSelected(cbAllFeatures.isSelected());
		cbSmallestLapEgv.setSelected(cbAllFeatures.isSelected());
		cbGapLargestAndSmallestNZLapEgv.setSelected(cbAllFeatures.isSelected());
		
		//Graph Spectra - Distance Matrix
		cbWienerIndex.setSelected(cbAllFeatures.isSelected());
		cbPathLength.setSelected(cbAllFeatures.isSelected());
		cbGirth.setSelected(cbAllFeatures.isSelected());
		cbConnectedComponents.setSelected(cbAllFeatures.isSelected());
		cbRank.setSelected(cbAllFeatures.isSelected());
		cbCoRank.setSelected(cbAllFeatures.isSelected());
		
		cbLargestMaximalClique.setSelected(cbAllFeatures.isSelected());
		
		cbDegeneracy.setSelected(cbAllFeatures.isSelected());
		
		countNumberOfFeatures(event);
	}

	/*
	 * Counts and update the number of features selected, presenting it to the user
	 */
	@FXML protected void countNumberOfFeatures(MouseEvent event){
		int count = 0;
		if (cbNodes.isSelected()) count++;
		if (cbEdges.isSelected()) count++;
		if (cbNodesEdges.isSelected()) count++;
		if (cbEdgesNodes.isSelected()) count++;
		if (cbDensity.isSelected()) count++;

		if (cbMinDegree.isSelected()) count++;
		if (cbMaxDegree.isSelected()) count++;
		if (cbMeanDegree.isSelected()) count++;
		if (cbStdDegree.isSelected()) count++;
		if (cbVCDegree.isSelected()) count++;
		if (cbMedianDegree.isSelected()) count++;
		if (cbQ1Degree.isSelected()) count++;
		if (cbQ3Degree.isSelected()) count++;

		if (cbMinBetweenness.isSelected()) count++;
		if (cbMaxBetweenness.isSelected()) count++;
		if (cbMeanBetweenness.isSelected()) count++;
		if (cbStdBetweenness.isSelected()) count++;
		if (cbVCBetweenness.isSelected()) count++;
		if (cbMedianBetweenness.isSelected()) count++;
		if (cbQ1Betweenness.isSelected()) count++;
		if (cbQ3Betweenness.isSelected()) count++;

		if (cbMinCloseness.isSelected()) count++;
		if (cbMaxCloseness.isSelected()) count++;
		if (cbMeanCloseness.isSelected()) count++;
		if (cbStdCloseness.isSelected()) count++;
		if (cbVCCloseness.isSelected()) count++;
		if (cbMedianCloseness.isSelected()) count++;
		if (cbQ1Closeness.isSelected()) count++;
		if (cbQ3Closeness.isSelected()) count++;

		if (cbMinEigenvector.isSelected()) count++;
		if (cbMaxEigenvector.isSelected()) count++;
		if (cbMeanEigenvector.isSelected()) count++;
		if (cbStdEigenvector.isSelected()) count++;
		if (cbVCEigenvector.isSelected()) count++;
		if (cbMedianEigenvector.isSelected()) count++;	
		if (cbQ1Eigenvector.isSelected()) count++;	
		if (cbQ3Eigenvector.isSelected()) count++;	

		if (cbMinEccentricity.isSelected()) count++;
		if (cbMaxEccentricity.isSelected()) count++;
		if (cbMeanEccentricity.isSelected()) count++;
		if (cbStdEccentricity.isSelected()) count++;
		if (cbVCEccentricity.isSelected()) count++;
		if (cbMedianEccentricity.isSelected()) count++;
		if (cbQ1Eccentricity.isSelected()) count++;
		if (cbQ3Eccentricity.isSelected()) count++;

		if (cbMinClustering.isSelected()) count++;
		if (cbMaxClustering.isSelected()) count++;
		if (cbMeanClustering.isSelected()) count++;
		if (cbStdClustering.isSelected()) count++;
		if (cbVCClustering.isSelected()) count++;
		if (cbMedianClustering.isSelected()) count++;
		if (cbQ1Clustering.isSelected()) count++;
		if (cbQ3Clustering.isSelected()) count++;

		if (cbMinWClustering.isSelected()) count++;
		if (cbMaxWClustering.isSelected()) count++;
		if (cbMeanWClustering.isSelected()) count++;
		if (cbStdWClustering.isSelected()) count++;
		if (cbVCWClustering.isSelected()) count++;
		if (cbMedianWClustering.isSelected()) count++;
		if (cbQ1WClustering.isSelected()) count++;
		if (cbQ3WClustering.isSelected()) count++;
		
		//Graph Spectra - Adjacency Matrix
		if (cbIndex.isSelected()) count++;
		if (cb2ndLargestAdjEgv.isSelected()) count++;
		if (cb2ndSmallestAdjEgv.isSelected()) count++;
		if (cbSmallestAdjEgv.isSelected()) count++;
		if (cbMeanSpectrum.isSelected()) count++;
		if (cbStdSpectrum.isSelected()) count++;
		if (cbVCSpectrum.isSelected()) count++;
		if (cbEnergy.isSelected()) count++;
		if (cbGapLargestAnd2ndLargestAdjEgv.isSelected()) count++;
		
		//Graph Spectra - Laplacian Matrix
		if (cbLaplacianIndex.isSelected()) count++;
		if (cb2ndLargestLapEgv.isSelected()) count++;
		if (cbSmallestNZLapEgv.isSelected()) count++;
		if (cb2ndSmallestNZLapEgv.isSelected()) count++;
		if (cbAlgConnectivity.isSelected()) count++;
		if (cbSmallestLapEgv.isSelected()) count++;
		if (cbGapLargestAndSmallestNZLapEgv.isSelected()) count++;
		
		//Distance Matrix
		if (cbWienerIndex.isSelected()) count++;
		if (cbPathLength.isSelected()) count++;
		if (cbGirth.isSelected()) count++;
		if (cbConnectedComponents.isSelected()) count++;
		if (cbRank.isSelected()) count++;
		if (cbCoRank.isSelected()) count++;
		
		if (cbLargestMaximalClique.isSelected()) count++;
		if (cbDegeneracy.isSelected()) count++;
		
		lFeaturesSelected.setText("Features Selected: "+count);

	}
	
}